其實我覺得很多模式實踐起來真的不難,但是在實踐之前要先知道
有這個模式,所以四人幫(Gang of four)幫我們整理出這些模式,真的很有意義,本來以為已經會的東西,再重新看過之後發現,其實還有很多可以實踐在現有的程式碼,或是某些模式以前以為了解了但是其實不夠透測,有些相似的模式一直重複出現的代表是重點呢!
Google首頁的萬聖節遊戲好玩XD快找朋友體驗看看吧!
昨天介紹了外觀模式,在外觀模式(Facade)中可以整理出一個整潔的介面
(類別),或是可以把外觀模式當作重構的起點。在狀態模式中,則是固定的運算或動作,在不同的狀態之下會改變,所以將改變後各個狀態的動作封裝起來,客戶端只要改變狀態,即可針對不同的狀態作出正確的行為。
狀態模式 ( State ) ,當一個物件的內在狀態改變時允許改變其行為,這個物件看起來像是改變了其類別。
-- 大話設計模式 p.239
將行為用一個介面封裝起來,針對不同的狀態去改變其行為。
狀態改變的同時行為也改變
。在執行環境( Context )中,只需要改變狀態,而不需要管對應各個狀態時行為的不同。
假設我們儲存的資料是公制,但是要根據顯示的設定切換顯示公制和英制的數值、以及儲存的數值···
狀態的interface
public abstract class State {
// 顯示的數值
abstract public String tempToDisplay(Double temperture);
abstract public String vibToDisplay(Double vibration);
// 儲存的數值
abstract public String tempToSave(Double temperture);
abstract public String vibToSave(Double vibration);
// 精準到小數點下兩位
public static String twoDecPlaces(Double value){
return String.format("%.2f",value);
}
public static String saveForm(Double value){
return String.format("%f",value);
}
}
公制的State
public class Metric extends State {
@Override
public String tempToDisplay(Double temperture) {
System.out.println("顯示公制");
return twoDecPlaces(temperture);
}
@Override
public String vibToDisplay(Double vibration) {
System.out.println("顯示公制");
return twoDecPlaces(vibration);
}
@Override
public String tempToSave(Double temperture) {
System.out.println("儲存公制");
return saveForm(temperture);
}
@Override
public String vibToSave(Double vibration) {
System.out.println("儲存公制");
return saveForm(vibration);
}
}
英制的State
public class British extends State {
// 英制資料儲存成公制
@Override
public String tempToDisplay(Double temperture) {
System.out.println("顯示英制");
return twoDecPlaces(temperture * 9 / 5 + 32);
}
@Override
public String vibToDisplay(Double vibration) {
System.out.println("顯示英制");
return twoDecPlaces(vibration * 25.4);
}
// 公制資料顯示成英制
@Override
public String tempToSave(Double temperture) {
System.out.println("儲存英制");
return saveForm((temperture - 32) * 5 / 9);
}
@Override
public String vibToSave(Double vibration) {
System.out.println("儲存英制");
return saveForm(vibration/25.4);
}
}
選擇是哪一種狀態的環境 (Context)
public class MetricSystem {
private State state;
public void setState(final State state) {
this.state = state;
}
public void tempView(Double temp){
System.out.println(state.tempToDisplay(temp));
}
public void vibView(Double vib){
System.out.println(state.vibToDisplay(vib));
}
public void tempSave(Double temp){
System.out.println(state.tempToSave(temp));
}
public void vibSave(Double vib){
System.out.println(state.vibToSave(vib));
}
}
public class Test {
@org.junit.jupiter.api.Test
public void test(){
MetricSystem metricSystem = new MetricSystem();
metricSystem.setState(new Metric());
metricSystem.tempView(50d);
metricSystem.vibView(10d);
metricSystem.tempSave(50d);
metricSystem.vibSave(10d);
metricSystem.setState(new British());
metricSystem.tempView(50d);
metricSystem.vibView(10d);
metricSystem.tempSave(50d);
metricSystem.vibSave(10d);
}
}
測試結果
顯示公制
50.00
顯示公制
10.00
儲存公制
50.000000
儲存公制
10.000000
顯示英制
122.00
顯示英制
254.00
儲存英制
10.000000
儲存英制
0.393701
狀態模式的案例就討論到這邊~如果有什麼更好的例子歡迎留言或私訊我,感恩!